#include <stdio.h>
#include <stdlib.h>
#include <sched.h>
#include <errno.h>
#include <unistd.h>
#include <string.h>
#include <sys/wait.h>
#include "hw2_syscalls.h"


int fibonaci(int n){
	if (n<2)
		return n;
	return fibonaci(n-1)+fibonaci(n-2);

}

const char * reason_to_str(enum sched_reason reason)
{
	switch (reason) {
	case SWITCH_REASON_CREATE:
		return "SWITCH_REASON_CREATE";
	case SWITCH_REASON_END:
		return "SWITCH_REASON_END";
	case SWITCH_REASON_YIELD:
		return "SWITCH_REASON_YIELD";
	case SWITCH_REASON_MQ_OVERDUE:
		return "SWITCH_REASON_MQ_OVERDUE";
	case SWITCH_REASON_TO_WAIT:
		return "SWITCH_REASON_TO_WAIT";
	case SWITCH_REASON_FROM_WAIT:
		return "SWITCH_REASON_FROM_WAIT";
	case SWITCH_REASON_TIMESLICE_END:
		return "SWITCH_REASON_TIMESLICE_END";
	case SWITCH_REASON_INVALID:
		return "SWITCH_REASON_INVALID";
	default:
		return "SWITCH_REASON_???";
	}
}

const char* policy_to_str(int policy)
{
    switch (policy) {
    case 0:
        return "OTHER";
    case 1:
        return "FIFO";
    case 2:
        return "RR";
    case 4:
        return "MQ";
    }

    return "????";
}


void print_statistics()
{
	struct switch_info info[150];
	int i, res;

	res = get_scheduling_statistic(info);
	if(res == 0 ) {
	    exit(0);
	}
	printf("\nPREV_PID  |NEXT_PID  |PREV_POLICY |NEXT_POLICY |TIME      |REASON    \n");
	for(i = 0 ; i < res; i++){
	    printf("%10d|%10d|%12s|%12s|%10lu|%10s\n",
	     info[i].previous_pid, info[i].next_pid, policy_to_str(info[i].previous_policy),
	     policy_to_str(info[i].next_policy), info[i].time, reason_to_str(info[i].reason));
	}

}



int main(int argc, char** argv){
	int i,res;
	struct switch_info array[150];
	if ((argc%2) != 1){
		printf("input error\n");
		return 0;
	}

	for(i=0; i<argc/2; i++){
		struct sched_param param;
		res = fork();
		if (!res){
			param.trial_num=atoi(argv[2*i+1]);
			param.sched_priority = 0;
			int res = sched_setscheduler(getpid(),SCHED_MQ,&param);

			if(res == -1){
			printf("TRIAL : %d, numberof trials : %d , n : %d , pid : %d \n", i, param.trial_num, atoi(argv[2*(i+1)]), getpid());
				//printf("ERROR IN input pid : %d\n", getpid());
			exit(1);
			}


			printf("TRIAL : %d, numberof trials : %d , n : %d , pid : %d \n", i, param.trial_num, atoi(argv[2*(i+1)]), getpid());
			fibonaci(atoi(argv[2*(i+1)]));
			return 0;
		}
	}

	while (wait(NULL) != -1) {};
	res=get_scheduling_statistic(array);
	print_statistics(res);

	return 0;
}
